def evalInvokeExpr(caches:scala.collection.mutable.Map[SymbolExpr,Expr],invokeExpr:InvokeExpr):Expr = {
      debugger.info(this, "evalInvokeExpr", List(caches,invokeExpr))
      var expr = this.getExpr(invokeExpr.symbol) //type
      if(expr == nil){
        expr = caches.getOrElse(invokeExpr.symbol, nil) //variable
      }
      if(expr == nil){ 
        throw ExprNotFoundException(invokeExpr.symbol)
      } else if(!expr.isInstanceOf[GraphExpr]){ //e.g. 3,"hello"
        return expr.eval()
        //throw ExprNotCallableException(expr)
      } else {
        //find definition
        val graph = expr.asInstanceOf[GraphExpr]
        if(graph.params.length != invokeExpr.params.length){
          throw ParamLengthMismatchException(graph)
        }
        
        //put params into defintion
        for(i <- Range(0,graph.params.length)){
          if(graph.params(i).isInstanceOf[SymbolExpr]){ //e.g. func(param1,param2){...}
            graph.params(i) = PairExpr(graph.params(i).asInstanceOf[SymbolExpr],nil)
          } else if(!graph.params(i).isInstanceOf[PairExpr]){ //e.g. func(param1:String,...){...}  error:func(1,"hi"){...}
            throw ParamsDefinedException(graph)
          }
          val graphParam = graph.params(i).asInstanceOf[PairExpr]
          val invokeParam = invokeExpr.params(i)
          
          if(invokeParam.isInstanceOf[InvokeExpr]){ //e.g. f(g(x),...)
            graphParam.value = evalInvokeExpr(caches,invokeParam.asInstanceOf[InvokeExpr])
          } else if(invokeParam.isInstanceOf[OperatorExpr]){ //e.g. f(a+b,...)
            graphParam.value = evalOperatorExpr(caches,invokeParam.asInstanceOf[OperatorExpr])
          } else if(invokeParam.isInstanceOf[SymbolExpr]){ //e.g. f(x)
            var expr = caches.getOrElse(invokeParam.asInstanceOf[SymbolExpr], nil)
            if(expr == nil){
              expr = this.getExpr(invokeParam.asInstanceOf[SymbolExpr])
            }
        	  graphParam.value = expr
          } else if(invokeParam.isInstanceOf[StringExpr] || invokeParam.isInstanceOf[NumberExpr]){ //e.g. f(3,"str")
            graphParam.value = invokeParam.eval()
          }
        }
        graph.eval()
      }
  }